namespace com.stifel.ServerBuildMgmt.Features.SeverBuildMgmtNotificationList
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.Xml;

    using com.stifel.Extensions.AssemblyExtensions;
    using com.stifel.Extensions.SharePointExtensions;
    using com.stifel.Extensions.SymbolExtensions;
    using com.stifel.ServerBuildMgmtDao;
    using com.stifel.SharePoint;

    using Microsoft.SharePoint;

    /// <summary>
    /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
    /// </summary>
    /// <remarks>
    /// The GUID attached to this class may be used during packaging and should not be modified.
    /// </remarks>
    [Guid( "1a634a38-cb85-498b-9ecb-13e1a89c26fe" )]
    public class SeverBuildMgmtNotificationListEventReceiver : SPFeatureReceiver
    {
        #region Fields

        public const string FEATURE = "com.stifel.ServerBuildMgmt";

        const string CONTENTTYPEGROUP = "Stifel Notification";

        List<string> fields1 = new string[ ] { "Stifel-Notification.xml" }.ToList( );
        List<ContentTypeDefn> _ContentTypes2;
        List<ListDefn> _NotificationList;

        #endregion Fields

        #region Properties

        List<ContentTypeDefn> ContentTypes2
        {
            get
            {
                if ( _ContentTypes2 == null )
                {
                    _ContentTypes2 = new List<ContentTypeDefn>( );
                    {
                        StifelNotification c = null;
                        _ContentTypes2.Add( new ContentTypeDefn
                        {
                            Name = Item.GetContentTypeName<StifelNotification>( ),
                            ContentTypeId = Item.GetContentTypeId<StifelNotification>( ),
                            Group = CONTENTTYPEGROUP,
                            Description = "Defines a notification.",
                            Fields = new FieldDefn[ ] {
                                new FieldDefn{ Name=Item.GetColumnName<StifelNotification>(c.GetPropertySymbol(o=>o.Notification))
                                },
                                new FieldDefn{
                                    Name=Item.GetColumnName<StifelNotification>(c.GetPropertySymbol(o=>o.NotificationURL))
                                },
                                new FieldDefn{
                                    Name=Item.GetColumnName<StifelNotification>(c.GetPropertySymbol(o=>o.RequestIdentifier))
                                },
                                new FieldDefn{
                                    Name=Item.GetColumnName<StifelNotification>(c.GetPropertySymbol(o=>o.RequestUniqueId))
                                }
                            }.Distinct( ).ToList( )
                        } );
                    }
                }
                return _ContentTypes2;
            }
        }

        List<ListDefn> NotificationList
        {
            get
            {
                if ( _NotificationList == null )
                {
                    _NotificationList = new List<ListDefn>( );
                    _NotificationList.Add( new ListDefn
                    {
                        Title = "Stifel Notification",
                        RootFolderName = "stifelnotification",
                        Description = "This contains notifications.",
                        ContentTypes = new string[ ] {
                            Item.GetContentTypeName<StifelNotification>()
                        }.ToList( )
                    } );
                }
                return _NotificationList;
            }
        }

        #endregion Properties

        #region Methods

        public override void FeatureActivated( SPFeatureReceiverProperties properties )
        {
            try
            {
                if ( !( properties.Feature.Parent is SPWeb ) )
                {
                    throw new Exception( string.Format( "{0} :: Error activating feature. Feature parent is not of type SPWEb.", FEATURE ) );
                }

                CustomLoggingService.LogMessage( CustomLoggingService.Area.FeatureInfrastructure, "{0} :: Feature activating.", FEATURE );
                addFields( properties, fields1 );
                createContentTypes( properties, ContentTypes2 );
                createLists( properties, NotificationList );
                CustomLoggingService.LogMessage( CustomLoggingService.Area.FeatureInfrastructure, "{0} :: Feature activated.", FEATURE );
            }
            catch ( Exception e )
            {
                throw new Exception( string.Format( "Error occurred in {0} FeatureActivated. {1} {2}", FEATURE, e.Message, e.StackTrace ), e );
            }
        }

        public override void FeatureDeactivating( SPFeatureReceiverProperties properties )
        {
            try
            {
                if ( !( properties.Feature.Parent is SPWeb ) )
                {
                    CustomLoggingService.LogCritical( CustomLoggingService.Area.FeatureInfrastructure, "{0} :: Error deactivating feature. Feature parent is not of type SPWeb.", FEATURE );
                    return;
                }

                CustomLoggingService.LogMessage( CustomLoggingService.Area.FeatureInfrastructure, "{0} :: Feature deactivating.", FEATURE );
                deleteLists( properties, NotificationList );
                deleteContentTypes( properties, ContentTypes2 );
                removeFields( properties, fields1 );
                CustomLoggingService.LogMessage( CustomLoggingService.Area.FeatureInfrastructure, "{0} :: Feature deactivated." );
            }
            catch ( Exception e )
            {
                throw new Exception( string.Format( "Error occurred in {0} FeatureDeactivating. {1} {2}", FEATURE, e.Message, e.StackTrace ), e );
            }
        }

        void addFields( SPFeatureReceiverProperties properties, List<string> fieldResource )
        {
            foreach ( string resource in fieldResource )
            {
                XmlNodeList fields = getFieldDefinitionsAsXml( resource );
                if ( fields != null )
                {
                    using ( SPSite spSite = new SPSite( properties.GetSite( ).Url ) )
                    {
                        using ( SPWeb spWeb = spSite.OpenWeb( ) )
                        {
                            foreach ( XmlNode field in fields )
                            {
                                XmlAttribute a = field.Attributes[ "Name" ];
                                if ( a != null )
                                {
                                    string name = a.Value;
                                    if ( !spWeb.Fields.ContainsFieldWithStaticName( name ) )
                                    {
                                        bool ok = true;
                                        string s = field.OuterXml;
                                        const string LISTMARKER = "List=\"$";
                                        if ( s.Contains( LISTMARKER ) )
                                        {
                                            int x1 = s.IndexOf( LISTMARKER ) + LISTMARKER.Length;
                                            int x2 = s.IndexOf( "$\"", x1 );
                                            string listurl = s.Substring( x1, x2 - x1 );
                                            if ( !string.IsNullOrEmpty( listurl ) )
                                            {
                                                SPList spList = spWeb.Lists.GetListByRootFolder( listurl );
                                                if ( spList != null )
                                                    s = s.Replace( string.Format( "\"${0}$\"", listurl ), string.Format( "\"{0}\"", spList.ID.ToString( "B" ) ) );
                                                else
                                                    ok = false;
                                            }
                                        }
                                        if ( ok )
                                        {
                                            CustomLoggingService.LogMessage( CustomLoggingService.Area.Fields, s );
                                            spWeb.Fields.AddFieldAsXml( s );
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        void createContentTypes( SPFeatureReceiverProperties properties, List<ContentTypeDefn> contenttypes )
        {
            using ( SPSite spSite = new SPSite( properties.GetSite( ).Url ) )
            {
                using ( SPWeb spWeb = spSite.OpenWeb( ) )
                {
                    foreach ( ContentTypeDefn o in contenttypes )
                    {
                        if ( !spWeb.ContainsContentType( o.Name ) )
                        {
                            List<SPField> fields = new List<SPField>( );
                            foreach ( FieldDefn f in o.Fields )
                            {
                                if ( f != null && !string.IsNullOrEmpty( f.Name ) )
                                {
                                    SPField field = spWeb.Fields.GetFieldByInternalName( f.Name );
                                    if ( field != null )
                                    {
                                        field.Required = f.Required;
                                        field.Hidden = f.Hidden;
                                        fields.Add( field );
                                    }
                                }
                            }
                            spWeb.CreateContentType( o.ContentTypeId, o.Group, o.Name, o.Description, false, fields.ToArray( ) );
                        }
                    }
                }
            }
        }

        void createLists( SPFeatureReceiverProperties properties, List<ListDefn> lists )
        {
            using ( SPWeb spWeb = properties.GetWeb( ) )
            {
                foreach ( ListDefn o in lists )
                {
                    if ( spWeb.Lists.ContainsList( o.RootFolderName ) )
                    {
                        CustomLoggingService.LogWarning( CustomLoggingService.Area.FeatureInfrastructure, "{0} :: List {1} not created. List already exists.", FEATURE, o.RootFolderName );
                    }
                    else
                    {
                        SPList spList = spWeb.CreateGenericList( o.RootFolderName, o.Title, o.Description, false );

                        spList.ContentTypesEnabled = true;

                        bool changes = false;
                        foreach ( SPContentType p in spList.ContentTypes )
                        {
                            if ( !p.Sealed )
                            {
                                p.Hidden = true;
                                p.Update( );
                                changes = true;
                            }
                        }
                        if ( changes )
                            spList.Update( );

                        changes = false;
                        foreach ( string s in o.ContentTypes )
                        {
                            SPContentType p = spWeb.GetContentTypeByName( s );
                            if ( p != null )
                            {
                                spList.ContentTypes.Add( p );
                                changes = true;
                            }
                        }
                        if ( changes )
                        {
                            spList.Update( );

                            List<SPContentType> contentTypeOrder = spList.RootFolder.ContentTypeOrder.ToList( );
                            contentTypeOrder.Reverse( );
                            spList.RootFolder.UniqueContentTypeOrder = contentTypeOrder;
                            spList.RootFolder.Update( );
                        }

                        CustomLoggingService.LogMessage( CustomLoggingService.Area.FeatureInfrastructure, "{0} :: List {1} created.", FEATURE, o.RootFolderName );
                    }
                }
            }
        }

        void deleteContentTypes( SPFeatureReceiverProperties properties, List<ContentTypeDefn> contenttypes )
        {
            using ( SPSite spSite = new SPSite( properties.GetSite( ).Url ) )
            {
                using ( SPWeb spWeb = spSite.OpenWeb( ) )
                {
                    foreach ( ContentTypeDefn o in contenttypes )
                        spWeb.DeleteContentType( o.Name );
                }
            }
        }

        void deleteLists( SPFeatureReceiverProperties properties, List<ListDefn> lists )
        {
            using ( SPWeb spWeb = properties.GetWeb( ) )
            {
                foreach ( ListDefn list in lists )
                {
                    bool ok = spWeb.DeleteList( list.RootFolderName, false );
                    if ( ok )
                        CustomLoggingService.LogMessage( CustomLoggingService.Area.FeatureInfrastructure, "{0} :: List {1} removed.", FEATURE, list.RootFolderName );
                    else
                        CustomLoggingService.LogMessage( CustomLoggingService.Area.FeatureInfrastructure, "{0} :: List {1} not removed.", FEATURE, list.RootFolderName );
                }
            }
        }

        XmlNodeList getFieldDefinitionsAsXml( string resource )
        {
            XmlNodeList fields = null;
            string s = Assembly.GetExecutingAssembly( ).GetFullyQualifiedManifestResourceName( resource );
            string xml = Assembly.GetExecutingAssembly( ).GetManifestResourceAsString( s );
            if ( !string.IsNullOrEmpty( xml ) )
            {
                XmlDocument d = new XmlDocument( );
                d.LoadXml( xml );
                XmlNode n = d.SelectSingleNode( "Fields" );
                fields = n.SelectNodes( "Field" );
            }
            return fields;
        }

        void removeFields( SPFeatureReceiverProperties properties, List<string> fieldResource )
        {
            foreach ( string resource in fieldResource )
            {
                XmlNodeList fields = getFieldDefinitionsAsXml( resource );
                if ( fields != null )
                {
                    using ( SPSite spSite = new SPSite( properties.GetSite( ).Url ) )
                    {
                        using ( SPWeb spWeb = spSite.OpenWeb( ) )
                        {
                            foreach ( XmlNode field in fields )
                            {
                                XmlAttribute a = field.Attributes[ "Name" ];
                                if ( a != null )
                                {
                                    string name = a.Value;
                                    if ( spWeb.Fields.ContainsFieldWithStaticName( name ) )
                                    {
                                        SPField f = spWeb.Fields.GetFieldByInternalName( name );
                                        if ( !f.UsedInWebContentTypes )
                                            spWeb.Fields.Delete( name );
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        #endregion Methods

        #region Other

        // Uncomment the method below to handle the event raised after a feature has been installed.
        //public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        //{
        //}
        // Uncomment the method below to handle the event raised before a feature is uninstalled.
        //public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        //{
        //}
        // Uncomment the method below to handle the event raised when a feature is upgrading.
        //public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)
        //{
        //}

        #endregion Other
    }
}